home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 6 / develop 6 code / TCP / NewsWatcher / NewsWatcher 2.0d15 source / source / dlgutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-29  |  41.6 KB  |  1,554 lines  |  [TEXT/KAHL]

  1. /*----------------------------------------------------------------------------
  2.  
  3.     dlgutil.c
  4.  
  5.     This module contains miscellaneous dialog utility routines.
  6.     
  7.     Portions copyright © 1990, Apple Computer.
  8.     Portions copyright © 1993, Northwestern University.
  9.  
  10. ----------------------------------------------------------------------------*/
  11.  
  12. #include "MacTCPCommonTypes.h"
  13. #include <Packages.h>
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <string.h>
  17.  
  18. #include "glob.h"
  19. #include "dlgutil.h"
  20. #include "util.h"
  21. #include "activate.h"
  22. #include "draw.h"
  23. #include "popup.h"
  24. #include "menus.h"
  25.  
  26.  
  27. #define kNewsWatcherSmallIconID        128        /* Small program icon */
  28.  
  29. #define kErrDlg                130            /* Error message dialog */
  30.  
  31. #define kServerErrDlg        131            /* News server error message dialog */
  32.  
  33. #define kNewsServerErrorMessageStaticTextItem        3
  34. #define kNewsServerErrorMessageGrayBorderUserItem    4
  35. #define kNewsServerErrorMessageTheMessageItem        5
  36. #define kNewsServerErrorMessageBozoTextUserItem     6
  37. #define kNewsServerErrorMessageBozoText                129
  38.  
  39. #define kMailFTPErrDlg        139            /* Mail & FTP server error message dialog */
  40.  
  41. #define kMailFTPErrorMessageGrayBorderUserItem        4
  42. #define kMailFTPErrorMessageTheMessageItem            5
  43.  
  44. #define kUnexpectedErrDlg    143            /* Unexpected error dialog */
  45.  
  46.  
  47.  
  48. static Str255 gServerErrorMessageStaticText;
  49. static Str255 gServerErrorMessageTheMessage;
  50.  
  51.  
  52.  
  53. typedef struct TDialogItemInfo {
  54.     Boolean numeric;                /* true if numeric textedit field */
  55.     Boolean returnIsLegal;            /* true if Return is legal in textedit field */
  56.     short popupTypeinItem;            /* item number of partner typein field for popup item,
  57.                                        or 0 if none */
  58.     char keyEquivalent;                /* command key equivalent for button, or 0 if none */
  59.     short maxLength;                /* max length of textedit field */
  60.     char *password;                    /* pointer to password if password field, or nil */
  61.     Boolean readOnly;                /* true if read only text field with scroll bar */
  62.     TEHandle readOnlyTE;            /* textedit handle for read only text field */
  63.     ControlHandle vScroll;            /* handle to vertical scroll bar control if read only
  64.                                        text field, or nil if none */
  65. } TDialogItemInfo;
  66.  
  67. typedef struct TDialogInfo {
  68.     Boolean returnIsOK;                /* true if return is equivalent to OK button */
  69.     Boolean hasCancelButton;        /* true if dialog has Cancel button */
  70.     CustomCopyCommandHandler customCopyCommandHandler;    /* pointer to custom Copy command
  71.                                                            handler, or nil if none */
  72.     TDialogItemInfo    itemInfo[];        /* array of item information */
  73. } TDialogInfo;
  74.  
  75.  
  76.  
  77.  
  78. /*----------------------------------------------------------------------------
  79.     DlgGetCheck 
  80.     
  81.     Gets the state of a checkbox in a dialog.
  82.     
  83.     Entry:    dlg = pointer to dialog.
  84.             item = item number of checkbox control.
  85.             
  86.     Exit:    function result = true if checked, false if unchecked.
  87. ----------------------------------------------------------------------------*/
  88.  
  89. Boolean DlgGetCheck (DialogPtr dlg, short item)
  90. {
  91.     Handle itemHandle;
  92.     short itemType;
  93.     Rect box;
  94.     
  95.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  96.     return (GetCtlValue((ControlHandle)itemHandle) == 1);
  97. }
  98.  
  99.  
  100.  
  101. /*----------------------------------------------------------------------------
  102.     DlgSetCheck 
  103.     
  104.     Sets the state of a checkbox in a dialog.
  105.     
  106.     Entry:    dlg = pointer to dialog.
  107.             item = item number of checkbox control.
  108.             value = true to check, false to uncheck.
  109. ----------------------------------------------------------------------------*/
  110.  
  111. void DlgSetCheck (DialogPtr dlg, short item, Boolean value)
  112. {
  113.     Handle itemHandle;
  114.     short itemType;
  115.     Rect box;
  116.     
  117.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  118.     SetCtlValue((ControlHandle)itemHandle,value);
  119. }
  120.  
  121.  
  122.  
  123. /*----------------------------------------------------------------------------
  124.     DlgToggleCheck 
  125.     
  126.     Toggles the state of a checkbox in a dialog.
  127.     
  128.     Entry:    dlg = pointer to dialog.
  129.             item = item number of checkbox control.
  130.  
  131. ----------------------------------------------------------------------------*/
  132.  
  133. void DlgToggleCheck (DialogPtr dlg, short item)
  134. {
  135.     Handle itemHandle;
  136.     short itemType;
  137.     Rect box;
  138.     short value;
  139.     
  140.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  141.     value = (GetCtlValue((ControlHandle)itemHandle) == 1) ? 0 : 1;
  142.     SetCtlValue((ControlHandle)itemHandle,value);
  143. }
  144.  
  145.  
  146.  
  147. /*----------------------------------------------------------------------------
  148.     DlgGetControl
  149.     
  150.     Gets the control handle for a dialog item.
  151.     
  152.     Entry:    dlg = pointer to dialog.
  153.             item = item number of control item.
  154.             
  155.     Exit:    function result = handle to control.
  156. ----------------------------------------------------------------------------*/
  157.  
  158. ControlHandle DlgGetControl (DialogPtr dlg, short item)
  159. {
  160.     Handle itemHandle;
  161.     short itemType;
  162.     Rect box;
  163.  
  164.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  165.     return (ControlHandle)itemHandle;
  166. }
  167.  
  168.  
  169.  
  170. /*----------------------------------------------------------------------------
  171.     DlgGetCtlValue 
  172.     
  173.     Gets the value of a control in a dialog.
  174.     
  175.     Entry:    dlg = pointer to dialog.
  176.             item = item number of  control.
  177.             
  178.     Exit:    function result = value of control.
  179. ----------------------------------------------------------------------------*/
  180.  
  181. short DlgGetCtlValue (DialogPtr dlg, short item)
  182. {
  183.     Handle itemHandle;
  184.     short itemType;
  185.     Rect box;
  186.     
  187.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  188.     return GetCtlValue((ControlHandle)itemHandle);
  189. }
  190.  
  191.  
  192.  
  193. /*----------------------------------------------------------------------------
  194.     DlgSetCtlValue 
  195.     
  196.     Sets the value of a control in a dialog.
  197.     
  198.     Entry:    dlg = pointer to dialog.
  199.             item = item number of checkbox control.
  200.             value = new control value.
  201. ----------------------------------------------------------------------------*/
  202.  
  203. void DlgSetCtlValue (DialogPtr dlg, short item, short value)
  204. {
  205.     Handle itemHandle;
  206.     short itemType;
  207.     Rect box;
  208.     
  209.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  210.     SetCtlValue((ControlHandle)itemHandle, value);
  211. }
  212.  
  213.  
  214.  
  215. /*----------------------------------------------------------------------------
  216.     DlgGetNumber 
  217.     
  218.     Gets the value of a numeric dialog item.
  219.     
  220.     Entry:    dlg = pointer to dialog.
  221.             item = item number.
  222.             
  223.     Exit:    function result = numeric value of item.
  224. ----------------------------------------------------------------------------*/
  225.  
  226. short DlgGetNumber (DialogPtr dlg, short item)
  227. {
  228.     Handle itemHandle;
  229.     short itemType;
  230.     Rect box;
  231.     Str255 valStr;
  232.     long value;
  233.     
  234.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  235.     GetIText(itemHandle, valStr);
  236.     StringToNum(valStr, &value);
  237.     return (short)value;
  238. }
  239.  
  240.  
  241.  
  242. /*----------------------------------------------------------------------------
  243.     DlgSetNumber 
  244.     
  245.     Sets the value of a numeric dialog item.
  246.     
  247.     Entry:    dlg = pointer to dialog.
  248.             item = item number.
  249.             value = new value for item.
  250. ----------------------------------------------------------------------------*/
  251.  
  252. void DlgSetNumber (DialogPtr dlg, short item, short value)
  253. {
  254.     Handle itemHandle;
  255.     short itemType;
  256.     Rect box;
  257.     Str255 valStr;
  258.     
  259.     NumToString(value, valStr);
  260.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  261.     SetIText(itemHandle, valStr);
  262. }
  263.  
  264.  
  265.  
  266. /*----------------------------------------------------------------------------
  267.     DlgGetCString 
  268.     
  269.     Gets the value of a string dialog item.
  270.     
  271.     Entry:    dlg = pointer to dialog.
  272.             item = item number.
  273.             
  274.     Exit:    value = the string (C format).
  275. ----------------------------------------------------------------------------*/
  276.  
  277. void DlgGetCString (DialogPtr dlg, short item, char *value)
  278. {
  279.     Handle itemHandle;
  280.     short itemType;
  281.     Rect box;
  282.     
  283.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  284.     GetIText(itemHandle, (StringPtr)value);
  285.     p2cstr((StringPtr)value);
  286. }
  287.  
  288.  
  289.  
  290. /*----------------------------------------------------------------------------
  291.     DlgSetCString 
  292.     
  293.     Sets the value of a string dialog item.
  294.     
  295.     Entry:    dlg = pointer to dialog.
  296.             item = item number.
  297.             value = new string value (C format).
  298. ----------------------------------------------------------------------------*/
  299.  
  300. void DlgSetCString (DialogPtr dlg, short item, char *value)
  301. {
  302.     Handle itemHandle;
  303.     short itemType;
  304.     Rect box;
  305.     
  306.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  307.     c2pstr(value);
  308.     SetIText(itemHandle, (StringPtr)value);
  309.     p2cstr((StringPtr)value);
  310. }
  311.  
  312.  
  313.  
  314. /*----------------------------------------------------------------------------
  315.     DlgGetPString
  316.     
  317.     Gets the value of a string dialog item.
  318.     
  319.     Entry:    dlg = pointer to dialog.
  320.             item = item number.
  321.             
  322.     Exit:    value = the string (Pascal format).
  323. ----------------------------------------------------------------------------*/
  324.  
  325. void DlgGetPString (DialogPtr dlg, short item, StringPtr value)
  326. {
  327.     Handle itemHandle;
  328.     short itemType;
  329.     Rect box;
  330.  
  331.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  332.     GetIText(itemHandle, value);
  333. }
  334.  
  335.  
  336.  
  337. /*----------------------------------------------------------------------------
  338.     DlgSetPString
  339.     
  340.     Sets the value of a string dialog item.
  341.     
  342.     Entry:    dlg = pointer to dialog.
  343.             item = item number.
  344.             value = new string value (Pascal format).
  345. ----------------------------------------------------------------------------*/
  346.  
  347. void DlgSetPString (DialogPtr dlg, short item, StringPtr value)
  348. {
  349.     Handle itemHandle;
  350.     short itemType;
  351.     Rect box;
  352.  
  353.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  354.     SetIText(itemHandle, value);
  355. }
  356.  
  357.  
  358.  
  359. /*----------------------------------------------------------------------------
  360.     DlgEnableItem
  361.     
  362.     Enables or disables an item in a dialog box. Checks to see if the item 
  363.     is a control and calls HiliteControl if so. Also redraws the outline 
  364.     around the default button if it's what's being enabled or disabled.
  365.     
  366.     Entry:    dlg = pointer to dialog.
  367.             item = item number of checkbox control.
  368.             enabled = new enabled state.
  369. ----------------------------------------------------------------------------*/
  370.  
  371. void DlgEnableItem (DialogPtr dlg, short item, Boolean enabled)
  372. {
  373.     Handle itemHandle;
  374.     short itemType;
  375.     Rect box;
  376.     Boolean    oldEnable;
  377.  
  378.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  379.     oldEnable = (itemType & itemDisable) == 0;
  380.     itemType = enabled ? itemType & (~itemDisable) : itemType | itemDisable;
  381.     SetDItem(dlg, item, itemType, itemHandle, &box);
  382.     
  383.     SetPort(dlg);
  384.     if ((itemType & ctrlItem) && oldEnable != enabled) {
  385.         if (item == ok) {
  386.             InsetRect(&box, -4, -4);
  387.             InvalRect(&box);
  388.             EraseRect(&box);
  389.         }
  390.         HiliteControl((ControlHandle)itemHandle, enabled ? 0 : 255);
  391.     }
  392. }
  393.  
  394.  
  395.  
  396. /*----------------------------------------------------------------------------
  397.     DlgSetUserItem
  398.     
  399.     Sets the procedure for a user item in a dialog.
  400.     
  401.     Entry:    dlg = pointer to dialog.
  402.             item = item number.
  403.             proc = pointer to user item proc.
  404. ----------------------------------------------------------------------------*/
  405.  
  406. void DlgSetUserItem (DialogPtr dlg, short item, UserItemProcPtr proc)
  407. {
  408.     Handle itemHandle;
  409.     short itemType;
  410.     Rect box;
  411.  
  412.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  413.     SetDItem(dlg, item, itemType, (Handle)proc, &box);
  414. }
  415.  
  416.  
  417.  
  418. /*----------------------------------------------------------------------------
  419.     DlgSetPict
  420.     
  421.     Set a dialog picture.
  422.     
  423.     Entry:    dlg = pointer to dialog.
  424.             item = item number of picture item.
  425.             pict = handle to picture.
  426. ----------------------------------------------------------------------------*/
  427.  
  428.  
  429. void DlgSetPict (DialogPtr dlg, short item, PicHandle pict)
  430. {
  431.     Handle itemHandle;
  432.     short itemType;
  433.     Rect box;
  434.     
  435.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  436.     SetDItem(dlg, item, itemType, (Handle)pict, &box);
  437. }
  438.  
  439.  
  440.  
  441. /*----------------------------------------------------------------------------
  442.     DlgEraseItems
  443.     
  444.     Erase and invalidate the area occupied by the specified items in a dialog.
  445.     
  446.     Entry:    dlg = pointer to dialog.
  447.             first = first item number to erase.
  448.             last = last item number to erase.
  449. ----------------------------------------------------------------------------*/
  450.  
  451. void DlgEraseItems (DialogPtr dlg, short first, short last)
  452. {
  453.     Rect itemRect;
  454.     Handle itemHandle;
  455.     short itemType, i;
  456.     
  457.     SetPort(dlg);
  458.     for (i = first; i <= last; i++) {
  459.         GetDItem(dlg, i, &itemType, &itemHandle, &itemRect);
  460.         if ((itemType & editText) ||
  461.             i == ok && (itemType & ctrlItem) && (itemType & 0x03) == btnCtrl) {
  462.             InsetRect(&itemRect, -4, -4);    /* Erase the border too */
  463.         }
  464.         EraseRect(&itemRect);
  465.         InvalRect(&itemRect);
  466.     }
  467. }
  468.  
  469.  
  470.  
  471. /*----------------------------------------------------------------------------
  472.     DlgGrayBorderItem
  473.     
  474.     A user item procedure to draw a dotted gray border around itself.
  475.     
  476.     Entry:    dlg = pointer to dialog.
  477.             item = item number.
  478. ----------------------------------------------------------------------------*/
  479.  
  480. pascal void DlgGrayBorderItem(DialogPtr dlg, short item)
  481. {
  482.     Handle itemHandle;
  483.     short itemType;
  484.     Rect box;
  485.     PenState savePen;
  486.  
  487.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  488.     GetPenState(&savePen);
  489.     PenNormal();
  490.     PenPat(qd.gray);
  491.     FrameRect(&box);
  492.     SetPenState(&savePen);
  493. }
  494.  
  495.  
  496.  
  497. /*----------------------------------------------------------------------------
  498.     DlgFlashButton
  499.  
  500.     Flashes a button.
  501.     
  502.     Entry:    dlg = pointer to dialog.
  503.             item = item number of button to flash.
  504. ----------------------------------------------------------------------------*/
  505.  
  506. void DlgFlashButton (DialogPtr dlg, short item)
  507. {
  508.     short itemType;
  509.     ControlHandle theItem;
  510.     Rect box;
  511.     long myticks;
  512.     
  513.     if (item > 0) {
  514.         GetDItem(dlg, item, &itemType, (Handle*)&theItem, &box);
  515.         HiliteControl(theItem, 1);
  516.         Delay(8, &myticks);
  517.         HiliteControl(theItem, 0);
  518.     }
  519. }
  520.  
  521.  
  522.  
  523. /*----------------------------------------------------------------------------
  524.     SetDialogCustomCopyHandler
  525.  
  526.     Sets a custom Copy command handler for a dialog.
  527.     
  528.     Entry:    dlg = pointer to dialog.
  529.             theHandler = pointer to custom Copy command handler.
  530. ----------------------------------------------------------------------------*/
  531.  
  532. void SetDialogCustomCopyHandler (DialogPtr dlg, CustomCopyCommandHandler theHandler)
  533. {
  534.     TDialogInfo **info;
  535.     
  536.     info = (TDialogInfo**)GetWRefCon(dlg);
  537.     (**info).customCopyCommandHandler = theHandler;
  538. }
  539.  
  540.  
  541.  
  542. /*----------------------------------------------------------------------------
  543.     SetItemNumeric
  544.  
  545.     Sets the "numeric" item info.
  546.     
  547.     Entry:    dlg = pointer to dialog.
  548.             item = item number of textedit field.
  549.             numeric = true if field is numeric (can only contain digits).
  550. ----------------------------------------------------------------------------*/
  551.  
  552. void SetItemNumeric (DialogPtr dlg, short item, Boolean numeric)
  553. {
  554.     TDialogInfo **info;
  555.     
  556.     info = (TDialogInfo**)GetWRefCon(dlg);
  557.     (**info).itemInfo[item-1].numeric = numeric;
  558. }
  559.  
  560.  
  561.  
  562. /*----------------------------------------------------------------------------
  563.     SetItemReturnIsLegal
  564.  
  565.     Sets the "returnIsLegal" item info.
  566.     
  567.     Entry:    dlg = pointer to dialog.
  568.             item = item number of textedit field.
  569.             returnIsLegal = true if the Return character is legal.
  570. ----------------------------------------------------------------------------*/
  571.  
  572. void SetItemReturnIsLegal (DialogPtr dlg, short item, Boolean returnIsLegal)
  573. {
  574.     TDialogInfo **info;
  575.     
  576.     info = (TDialogInfo**)GetWRefCon(dlg);
  577.     (**info).itemInfo[item-1].returnIsLegal = returnIsLegal;
  578. }
  579.  
  580.  
  581.  
  582. /*----------------------------------------------------------------------------
  583.     SetItemPopupTypeinItem
  584.  
  585.     Sets the "popupTypeinItem" item info.
  586.     
  587.     Entry:    dlg = pointer to dialog.
  588.             item = item number of popup menu control.
  589.             popupTypeInItem = item number of corresponding typein textedit
  590.                 field, or 0 if none.
  591. ----------------------------------------------------------------------------*/
  592.  
  593. void SetItemPopupTypeinItem (DialogPtr dlg, short item, short popupTypeinItem)
  594. {
  595.     TDialogInfo **info;
  596.     
  597.     info = (TDialogInfo**)GetWRefCon(dlg);
  598.     (**info).itemInfo[item-1].popupTypeinItem = popupTypeinItem;
  599. }
  600.  
  601.  
  602.  
  603. /*----------------------------------------------------------------------------
  604.     SetItemKeyEquivalent
  605.  
  606.     Sets the "keyEquivalent" item info.
  607.     
  608.     Entry:    dlg = pointer to dialog.
  609.             item = item number of push button control.
  610.             keyEquivalent = keyboard equivalent for control, or 0 if none.
  611. ----------------------------------------------------------------------------*/
  612.  
  613. void SetItemKeyEquivalent (DialogPtr dlg, short item, char keyEquivalent)
  614. {
  615.     TDialogInfo **info;
  616.     
  617.     info = (TDialogInfo**)GetWRefCon(dlg);
  618.     (**info).itemInfo[item-1].keyEquivalent = keyEquivalent;
  619. }
  620.  
  621.  
  622.  
  623. /*----------------------------------------------------------------------------
  624.     SetItemMaxLength
  625.  
  626.     Sets the "max length" item info.
  627.     
  628.     Entry:    dlg = pointer to dialog.
  629.             item = item number of textedit field.
  630.             maxLength = max length of field.
  631. ----------------------------------------------------------------------------*/
  632.  
  633. void SetItemMaxLength (DialogPtr dlg, short item, short maxLength)
  634. {
  635.     TDialogInfo **info;
  636.     
  637.     info = (TDialogInfo**)GetWRefCon(dlg);
  638.     (**info).itemInfo[item-1].maxLength = maxLength;
  639. }
  640.  
  641.  
  642.  
  643. /*----------------------------------------------------------------------------
  644.     SetItemPassword
  645.  
  646.     Sets the "password" item info.
  647.     
  648.     Entry:    dlg = pointer to dialog.
  649.             item = item number of textedit field.
  650.             password = pointer to password string, or nil if none.
  651. ----------------------------------------------------------------------------*/
  652.  
  653. void SetItemPassword (DialogPtr dlg, short item, char *password)
  654. {
  655.     TDialogInfo **info;
  656.     
  657.     info = (TDialogInfo**)GetWRefCon(dlg);
  658.     (**info).itemInfo[item-1].password = password;
  659. }
  660.  
  661.  
  662.  
  663. /*----------------------------------------------------------------------------
  664.     ReadOnlyUserItem
  665.     
  666.     The user item procedure to draw the contents of a read only text field.
  667.     
  668.     Entry:    dlg = pointer to dialog.
  669.             item = item number.
  670. ----------------------------------------------------------------------------*/
  671.  
  672. static pascal void ReadOnlyUserItem(DialogPtr dlg, short item)
  673. {
  674.     TDialogInfo **info;
  675.     Handle itemHandle;
  676.     short itemType;
  677.     Rect box;
  678.     PenState savePen;
  679.     
  680.     SetPort(dlg);
  681.     
  682.     info = (TDialogInfo**)GetWRefCon(dlg);
  683.  
  684.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  685.     GetPenState(&savePen);
  686.     PenNormal();
  687.     PenPat(qd.black);
  688.     FrameRect(&box);
  689.     SetPenState(&savePen);
  690.     
  691.     TEUpdate(&box, (**info).itemInfo[item-1].readOnlyTE);
  692. }
  693.  
  694.  
  695.  
  696. /*----------------------------------------------------------------------------
  697.     SetItemReadOnly
  698.  
  699.     Sets the "read only" item info.
  700.     
  701.     Entry:    dlg = pointer to dialog.
  702.             item = item number of textedit field.
  703.             theText = handle to contents of textedit field.
  704.             fontNum = font number for textedit field.
  705.             fontSize = font size for textedit field.
  706. ----------------------------------------------------------------------------*/
  707.  
  708. void SetItemReadOnly (DialogPtr dlg, short item, Handle theText, short fontNum, short fontSize)
  709. {
  710.     TDialogInfo **info;
  711.     short itemType;
  712.     Handle itemHandle;
  713.     Rect box;
  714.     TEHandle hTE;
  715.     short saveFont, saveSize;
  716.     Boolean needScrollBar;
  717.     FontInfo fontInfo;
  718.     short lineHeight, numLinesInBox;
  719.     
  720.     info = (TDialogInfo**)GetWRefCon(dlg);
  721.     (**info).itemInfo[item-1].readOnly = true;
  722.     DlgSetUserItem(dlg, item, ReadOnlyUserItem);
  723.  
  724.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  725.  
  726.     SetPort(dlg);
  727.     saveFont = dlg->txFont;
  728.     saveSize = dlg->txSize;
  729.     TextFont(fontNum);
  730.     TextSize(fontSize);
  731.     GetFontInfo(&fontInfo);
  732.     lineHeight = fontInfo.ascent+fontInfo.descent+fontInfo.leading;
  733.     numLinesInBox = (box.bottom - box.top - 2*kTextMargin) / lineHeight;
  734.     box.bottom = box.top + lineHeight * numLinesInBox + 2*kTextMargin;
  735.     SetDItem(dlg, item, itemType, itemHandle, &box);
  736.     
  737.     InsetRect(&box, kTextMargin, kTextMargin);
  738.     (**info).itemInfo[item-1].readOnlyTE = hTE = TENew(&box, &box);
  739.     HLock(theText);
  740.     TESetText(*theText, GetHandleSize(theText), hTE);
  741.     HUnlock(theText);
  742.     (**info).itemInfo[item-1].vScroll = nil;
  743.     
  744.     needScrollBar = (**hTE).nLines > numLinesInBox;
  745.     
  746.     if (needScrollBar) {
  747.         TEDispose(hTE);
  748.         box.right -= 16;
  749.         (**info).itemInfo[item-1].readOnlyTE = hTE = TENew(&box, &box);
  750.         HLock(theText);
  751.         TESetText(*theText, GetHandleSize(theText), hTE);
  752.         HUnlock(theText);
  753.         box.right += 16;
  754.         InsetRect(&box, -kTextMargin, -kTextMargin);
  755.         box.left = box.right - 16;
  756.         (**info).itemInfo[item-1].vScroll = NewControl(dlg, &box, "\p", true, 0, 0, 
  757.             (**hTE).nLines - numLinesInBox, scrollBarProc, item);
  758.     }
  759.     
  760.     TextFont(saveFont);
  761.     TextSize(saveSize);
  762. }
  763.  
  764.  
  765.  
  766. /*----------------------------------------------------------------------------
  767.     PrepDialog 
  768.     
  769.     Prepares for presenting a dialog:
  770. ----------------------------------------------------------------------------*/
  771.  
  772. void PrepDialog (void)
  773. {
  774.     WindowPtr wind;
  775.     NMRec nRec;
  776.  
  777.     CloseStatusWindow();
  778.     if (gInBackground) {
  779.         nRec.qType = nmType;
  780.         nRec.nmMark = 1;
  781.         nRec.nmIcon = GetResource('SICN', kNewsWatcherSmallIconID);
  782.         nRec.nmSound = nil;
  783.         nRec.nmStr = nil;
  784.         nRec.nmResp = nil;
  785.         NMInstall(&nRec);
  786.         while (gInBackground) GiveTime();
  787.         NMRemove(&nRec);
  788.     }
  789.     wind = FrontWindow();
  790.     if (IsAppWindow(wind)) {
  791.         HandleActivate(wind, false);
  792.         HandleUpdate(wind);
  793.     }
  794.     SetCursor(&qd.arrow);
  795. }
  796.  
  797.  
  798.  
  799. /*----------------------------------------------------------------------------
  800.     MyGetNewDialog 
  801.     
  802.     Gets a new dialog and intializes the dialog information.
  803.     
  804.     Entry:    id = resource id of DLOG resource.
  805.     
  806.     Exit:    function result = pointer to dialog record
  807. ----------------------------------------------------------------------------*/
  808.  
  809. DialogPtr MyGetNewDialog (short id)
  810. {
  811.     DialogPtr dlg;
  812.     TDialogInfo **info;
  813.     short numItems, i;
  814.     TDialogItemInfo itemInfo;
  815.  
  816.     PrepDialog();
  817.     dlg = GetNewDialog(id, nil, (WindowPtr)-1);
  818.     numItems = CountDITL(dlg);;
  819.     info = (TDialogInfo**)MyNewHandle(sizeof(TDialogInfo) + numItems*sizeof(TDialogItemInfo));
  820.     (**info).returnIsOK = true;
  821.     (**info).hasCancelButton = false;
  822.     (**info).customCopyCommandHandler = nil;
  823.     itemInfo.numeric = false;
  824.     itemInfo.returnIsLegal = false;
  825.     itemInfo.popupTypeinItem = 0;
  826.     itemInfo.keyEquivalent = 0;
  827.     itemInfo.maxLength = 0x7fff;
  828.     itemInfo.password = nil;
  829.     itemInfo.readOnly = false;
  830.     for (i = 0; i < numItems; i++) (**info).itemInfo[i] = itemInfo;
  831.     SetWRefCon(dlg, (long)info);
  832.     SetMenusTo(false, 0, 0, 0, 0, 0, 0);
  833.     HiliteMenu(0);
  834.     return dlg;
  835. }
  836.  
  837.  
  838.  
  839. /*----------------------------------------------------------------------------
  840.     MyDisposDialog 
  841.     
  842.     Disposes a dialog.
  843.     
  844.     Entry:    dlg = pointer to dialog.
  845. ----------------------------------------------------------------------------*/
  846.  
  847. void MyDisposDialog (DialogPtr dlg)
  848. {
  849.     TDialogInfo **info;
  850.     short itemNumber, numItems;
  851.     TDialogItemInfo *pItemInfo;
  852.  
  853.     info = (TDialogInfo**)GetWRefCon(dlg);
  854.     numItems = CountDITL(dlg);
  855.     HLock((Handle)info);
  856.     for (itemNumber = 1, pItemInfo = (**info).itemInfo; 
  857.         itemNumber <= numItems; 
  858.         itemNumber++, pItemInfo++) 
  859.     {
  860.         if (pItemInfo->readOnly) TEDispose(pItemInfo->readOnlyTE);
  861.     }
  862.     MyDisposHandle((Handle)info);
  863.     DisposDialog(dlg);
  864. }
  865.  
  866.  
  867.  
  868. /*----------------------------------------------------------------------------
  869.     MyShortenDITL
  870.     
  871.     Shortens a dialog's item list.
  872.     
  873.     Entry:    dlg = pointer to dialog.
  874.             numberItems = number of items to remove from the dialog item list.
  875. ----------------------------------------------------------------------------*/
  876.  
  877. void MyShortenDITL (DialogPtr dlg, short numberItems)
  878. {
  879.     TDialogInfo **info;
  880.     short numItems;
  881.     
  882.     ShortenDITL(dlg, numberItems);
  883.     info = (TDialogInfo**)GetWRefCon(dlg);
  884.     numItems = CountDITL(dlg);
  885.     MySetHandleSize((Handle)info, 
  886.         sizeof(TDialogInfo) + numItems*sizeof(TDialogItemInfo));
  887. }
  888.  
  889.  
  890.  
  891. /*----------------------------------------------------------------------------
  892.     MyAppendDITL 
  893.     
  894.     Adds items to a dialog's item list.
  895.     
  896.     Entry:    dlg = pointer to dialog.
  897.             theDITL = handle to item list to append.
  898.             theMethod = the manner in which the new items should be displayed,
  899.                 as in the Dialog Manger AppendDITL procedure.
  900. ----------------------------------------------------------------------------*/
  901.  
  902. void MyAppendDITL (DialogPtr dlg, Handle theDITL, DITLMethod theMethod)
  903. {
  904.     TDialogInfo **info;
  905.     TDialogItemInfo itemInfo;
  906.     short oldNumItems, numItems, i;
  907.  
  908.     oldNumItems = CountDITL(dlg);
  909.     AppendDITL(dlg, theDITL, theMethod);
  910.     info = (TDialogInfo**)GetWRefCon(dlg);
  911.     numItems = CountDITL(dlg);
  912.     MySetHandleSize((Handle)info, 
  913.         sizeof(TDialogInfo) + numItems*sizeof(TDialogItemInfo));
  914.     itemInfo.numeric = false;
  915.     itemInfo.returnIsLegal = false;
  916.     itemInfo.popupTypeinItem = 0;
  917.     itemInfo.keyEquivalent = 0;
  918.     itemInfo.maxLength = 0x7fff;
  919.     itemInfo.password = nil;
  920.     itemInfo.readOnly = false;
  921.     for (i = oldNumItems; i < numItems; i++) (**info).itemInfo[i] = itemInfo;
  922. }
  923.  
  924.  
  925.  
  926. /*----------------------------------------------------------------------------
  927.     ScrollAction 
  928.     
  929.     Action procedure for vertical scroll bars in dialog read only text fields.
  930.     
  931.     Entry:    dlg = pointer to dialog.
  932. ----------------------------------------------------------------------------*/
  933.  
  934. static pascal void ScrollAction (ControlHandle vScroll, short part)
  935. {
  936.     TDialogInfo **info;
  937.     short item;
  938.     TDialogItemInfo *pItemInfo;
  939.     TEHandle hTE;
  940.     short scrollAmt;
  941.     short lineHeight, pageSize;
  942.     short oldCtlValue, newCtlValue;
  943.     short min, max;
  944.     
  945.     info = (TDialogInfo**)GetWRefCon((**vScroll).contrlOwner);
  946.     item = GetCRefCon(vScroll);
  947.     pItemInfo = (**info).itemInfo + item - 1;
  948.     hTE = pItemInfo->readOnlyTE;
  949.     lineHeight = (**hTE).lineHeight;
  950.     pageSize = ((**hTE).viewRect.bottom - (**hTE).viewRect.top) / lineHeight - 1;
  951.     min = GetCtlMin(vScroll);
  952.     max = GetCtlMax(vScroll);
  953.     switch (part) {
  954.         case inUpButton:
  955.             scrollAmt = -1;
  956.             break;
  957.         case inDownButton:
  958.             scrollAmt = 1;
  959.             break;
  960.         case inPageUp:
  961.             scrollAmt = -pageSize;
  962.             break;
  963.         case inPageDown:
  964.             scrollAmt = pageSize;
  965.             break;
  966.     }
  967.     oldCtlValue = GetCtlValue(vScroll);
  968.     newCtlValue = oldCtlValue + scrollAmt;
  969.     if (newCtlValue < min) newCtlValue = min;
  970.     if (newCtlValue > max) newCtlValue = max;
  971.     if (newCtlValue == oldCtlValue) return;
  972.     SetCtlValue(vScroll, newCtlValue);
  973.     TEScroll(0, (oldCtlValue - newCtlValue) * lineHeight, hTE);
  974. }
  975.  
  976.  
  977.  
  978. /*----------------------------------------------------------------------------
  979.     DialogFilter 
  980.     
  981.     A humongous universal dialog filter which does all of the following 
  982.     gnarly stuff:
  983.     
  984.     Changes the cursor to an ibeam over textedit fields.
  985.     Handles the Return and Enter keyboard equivalents for the default button.
  986.     Handles the Command-Period and Escape keyboard equivalents for the 
  987.         Cancel button.
  988.     Properly flashes buttons when keyboard equivalents are used.
  989.     Properly handles update events for all windows.
  990.     Takes care of outlining the default button.
  991.     Permits the use of the Clear key in addition to the Delete key for 
  992.         deleting text.
  993.     Handles the forward delete key.
  994.     Properly adjusts the Edit menu and handles Edit menu commands.
  995.     Handles caller-defined custom Copy command handler for the entire dialog.
  996.     Handles caller-defined command key equivalents for push buttons.
  997.     Handles caller-defined numeric fields (non-digits are ignored).
  998.     Handles caller-defined definitions of which fields permit the Return key.
  999.     Handles caller-defined password fields (bullets displayed for security).
  1000.     Handles caller-defined typein popup menu controls (popup menus associated
  1001.         with a typein textedit field for specifying values not in the menu).
  1002.     Handles caller-defined max lengths for textedit fields.
  1003.     Handles caller-defined read only textedit fields with scroll bars.
  1004.         
  1005.     Entry:    dlg = pointer to dialog.
  1006.             *theEvent = event record.
  1007.             refcon field of dialog record = handle to TDialogInfo record.
  1008.             
  1009.     Exit:    function result = true if event handled.
  1010.             *itemHit = item number of item hit.
  1011. ----------------------------------------------------------------------------*/
  1012.  
  1013. pascal Boolean DialogFilter (DialogPtr dlg, EventRecord *theEvent, short *itemHit)
  1014. {
  1015.     char keyPressed, charPressed;
  1016.     short itemNumber;
  1017.     short numItems;
  1018.     short itemType;
  1019.     Handle itemHandle;
  1020.     Rect box;
  1021.     Boolean setCursorToIBeam;
  1022.     Point where;
  1023.     WindowPtr theWindow;
  1024.     PenState savePen;
  1025.     TEHandle hTE;
  1026.     TDialogInfo **info;
  1027.     TDialogItemInfo *pItemInfo;
  1028.     short editField;
  1029.     short part;
  1030.     short popupTypeinItem;
  1031.     Boolean numeric, returnIsLegal;
  1032.     short maxLength;
  1033.     ControlHandle popupCtl;
  1034.     Str255 str;
  1035.     Boolean commandKey;
  1036.     DialogPeek dPeek;
  1037.     short selStart, selEnd;
  1038.     char *password;
  1039.     short pwLen;
  1040.     unsigned long editMenuFlags;
  1041.     long menuSelection;
  1042.     Boolean isCommand = false;
  1043.     Boolean commandKeyIsButtonEquivalent = false;
  1044.     char *p, *pEnd;
  1045.     Boolean pasteOK = true;
  1046.     short nBullets;
  1047.     short theCommand;
  1048.     CustomCopyCommandHandler customCopyCommandHandler;
  1049.     Boolean readOnly;
  1050.     ControlHandle vScroll, control;
  1051.     short viewTop, destTop, oldScroll, scrollValue, height, newScroll, scrollDiff;
  1052.     Boolean setItemHit = false;
  1053.     
  1054.     SetPort(dlg);
  1055.     
  1056.     info = (TDialogInfo**)GetWRefCon(dlg);
  1057.     dPeek = (DialogPeek)dlg;
  1058.     numItems = **(short**)(dPeek->items) + 1;
  1059.     editField = dPeek->editField + 1;
  1060.     if (editField > 0) {
  1061.         hTE = dPeek->textH;
  1062.         selStart = (**hTE).selStart;
  1063.         selEnd = (**hTE).selEnd;
  1064.         pItemInfo = (**info).itemInfo + editField - 1;
  1065.         numeric = pItemInfo->numeric;
  1066.         returnIsLegal = pItemInfo->returnIsLegal;
  1067.         maxLength = pItemInfo->maxLength;
  1068.         password = pItemInfo->password;
  1069.         if (password != nil) pwLen = strlen(password);
  1070.     }
  1071.     
  1072.     GetMouse(&where);
  1073.     setCursorToIBeam = false;
  1074.     for (itemNumber = 1; itemNumber <= numItems; itemNumber++) {
  1075.         GetDItem(dlg, itemNumber, &itemType, &itemHandle, &box);
  1076.         if ((itemType & 0x7f) == editText && PtInRect(where, &box)) {
  1077.             setCursorToIBeam = true;
  1078.             break;
  1079.         }
  1080.     }
  1081.     SetCursor(setCursorToIBeam ? &gIBeamCurs : &qd.arrow);
  1082.     
  1083.     if ((**info).customCopyCommandHandler != nil) {
  1084.         editMenuFlags = kEntireMenuMask | kCopyMask;
  1085.         SetMenusTo(false, 0, editMenuFlags, 0, 0, 0, 0);
  1086.     } else if (editField > 0) {
  1087.         editMenuFlags = 0;
  1088.         if ((**hTE).teLength > 0) editMenuFlags |= kSelectAllMask;
  1089.         if (selStart < selEnd) editMenuFlags |= kCutMask | kCopyMask | kClearMask;
  1090.         TEFromScrap();
  1091.         if (TEScrpLength > 0) {
  1092.             if ((**hTE).teLength - (selEnd - selStart) + TEScrpLength <= maxLength) {
  1093.                 p = *TEScrpHandle;
  1094.                 pEnd = p + TEScrpLength;
  1095.                 while (p < pEnd) {
  1096.                     if (*p < ' ' && (*p != returnKey || !returnIsLegal)) {
  1097.                         pasteOK = false;
  1098.                         break;
  1099.                     }
  1100.                     if (numeric && (*p < '0' || *p > '9')) {
  1101.                         pasteOK = false;
  1102.                         break;
  1103.                     }
  1104.                     p++;
  1105.                 }        
  1106.                 if (pasteOK) editMenuFlags |= kPasteMask;
  1107.             }
  1108.         }
  1109.         if (editMenuFlags != 0) editMenuFlags |= kEntireMenuMask;
  1110.         SetMenusTo(false, 0, editMenuFlags, 0, 0, 0, 0);
  1111.     }
  1112.  
  1113.     if ((theEvent->what == keyDown)    || (theEvent->what == autoKey)) {
  1114.     
  1115.         charPressed = theEvent->message & charCodeMask;
  1116.         keyPressed = (theEvent->message & keyCodeMask) >> 8;
  1117.         commandKey = (theEvent->modifiers & cmdKey) != 0;
  1118.         if (!commandKey && ((charPressed == returnKey && (**info).returnIsOK) || 
  1119.             (charPressed == enterKey)))    
  1120.         {
  1121.             GetDItem(dlg, ok, &itemType, &itemHandle, &box);
  1122.             if (!(itemType & itemDisable)) {
  1123.                 *itemHit = ok;
  1124.                 DlgFlashButton(dlg, ok);
  1125.                 return true;
  1126.             } else {
  1127.                 theEvent->what = nullEvent;
  1128.             }
  1129.         } else if ((**info).hasCancelButton && 
  1130.             ((!commandKey && keyPressed == escapeKeyCode) ||
  1131.             (commandKey && charPressed == '.'))) 
  1132.         {
  1133.             GetDItem(dlg, cancel, &itemType, &itemHandle, &box);
  1134.             if (!(itemType & itemDisable)) {
  1135.                 *itemHit = cancel;
  1136.                 DlgFlashButton(dlg, cancel);
  1137.                 return true;
  1138.             } else {
  1139.                 theEvent->what = nullEvent;
  1140.             }
  1141.         } else if (commandKey) {
  1142.             HLock((Handle)info);
  1143.             for (itemNumber = 1, pItemInfo = (**info).itemInfo; 
  1144.                 itemNumber <= numItems; 
  1145.                 itemNumber++, pItemInfo++) 
  1146.             {
  1147.                 if (tolower(charPressed) == tolower(pItemInfo->keyEquivalent)) {
  1148.                     commandKeyIsButtonEquivalent = true;
  1149.                     GetDItem(dlg, itemNumber, &itemType, &itemHandle, &box);
  1150.                     if (!(itemType & itemDisable)) {
  1151.                         *itemHit = itemNumber;
  1152.                         DlgFlashButton(dlg, itemNumber);
  1153.                         HUnlock((Handle)info);
  1154.                         return true;
  1155.                     } else {
  1156.                         theEvent->what = nullEvent;
  1157.                     }
  1158.                 }
  1159.             }
  1160.             HUnlock((Handle)info);
  1161.             if (!commandKeyIsButtonEquivalent) {
  1162.                 menuSelection = MenuKey(charPressed);
  1163.                 isCommand = true;
  1164.             }
  1165.         }
  1166.         if (editField != 0 && theEvent->what != nullEvent && !commandKey) {
  1167.             if (keyPressed == clearKeyCode) theEvent->message = charPressed = deleteKey;
  1168.             switch (charPressed) {
  1169.                 case tabKey:
  1170.                 case leftArrow:
  1171.                 case rightArrow:
  1172.                 case upArrow:
  1173.                 case downArrow:
  1174.                     break;
  1175.                 case deleteKey:
  1176.                     if (password != nil) {
  1177.                         if (selStart == selEnd && selStart > 0) selStart--;
  1178.                         BlockMove(password + selEnd, password + selStart, pwLen - selEnd + 1);
  1179.                     }
  1180.                     break;
  1181.                 case returnKey:
  1182.                     if (!returnIsLegal) {
  1183.                         theEvent->what = nullEvent;
  1184.                         SysBeep(1);
  1185.                     }
  1186.                     break;
  1187.                 case forwardDelKey:
  1188.                     if (selStart == selEnd && selEnd < (**hTE).teLength) {
  1189.                         selEnd++;
  1190.                         (**hTE).selEnd = selEnd;
  1191.                     }
  1192.                     TEDelete(hTE);
  1193.                     if (password != nil) 
  1194.                         BlockMove(password + selEnd, password + selStart, pwLen - selEnd + 1);
  1195.                     *itemHit = editField;
  1196.                     return true;
  1197.                     break;
  1198.                 default:
  1199.                     if (charPressed < ' ' ||
  1200.                         numeric && !(charPressed >= '0' && charPressed <= '9') ||
  1201.                         (**hTE).teLength - (selEnd - selStart) + 1 > maxLength)
  1202.                     {
  1203.                         theEvent->what = nullEvent;
  1204.                         SysBeep(1);
  1205.                     } else if (password != nil) {
  1206.                         BlockMove(password + selEnd, password + selStart + 1, pwLen - selEnd + 1);
  1207.                         *(password + selStart) = charPressed;
  1208.                         theEvent->message = '•';
  1209.                     }
  1210.                     break;
  1211.             }
  1212.         }
  1213.     } else if (theEvent->what == updateEvt) {
  1214.         theWindow = (WindowPtr)theEvent->message;
  1215.         if (theWindow == dlg) {
  1216.             GetDItem(dlg, ok, &itemType, &itemHandle, &box);
  1217.             GetPenState(&savePen);
  1218.             PenSize(3,3);
  1219.             if (itemType & itemDisable) PenPat(qd.gray);
  1220.             InsetRect(&box, -4, -4);
  1221.             FrameRoundRect(&box, 16, 16);
  1222.             SetPenState(&savePen);
  1223.         } else {
  1224.             HandleUpdate(theWindow);
  1225.             SetPort(dlg);
  1226.         }
  1227.     } else if (theEvent->what == mouseDown) {
  1228.         where = theEvent->where;
  1229.         part = FindWindow(where, &theWindow);
  1230.         if (part == inMenuBar) {
  1231.             menuSelection = MenuSelect(where);
  1232.             isCommand = true;
  1233.         } else if (part == inContent && theWindow == dlg) {
  1234.             GlobalToLocal(&where);
  1235.             itemNumber = FindDItem(dlg, where) + 1;
  1236.             if (itemNumber > 0) {
  1237.                 pItemInfo = (**info).itemInfo + itemNumber - 1;
  1238.                 popupTypeinItem = pItemInfo->popupTypeinItem;
  1239.                 readOnly = pItemInfo->readOnly;
  1240.                 hTE = pItemInfo->readOnlyTE;
  1241.                 vScroll = pItemInfo->vScroll;
  1242.                 if (popupTypeinItem != 0) {
  1243.                     SelIText(dlg, popupTypeinItem, 0, 0x7fff);
  1244.                     DlgGetPString(dlg, popupTypeinItem, str);
  1245.                     popupCtl = DlgGetControl(dlg, itemNumber);
  1246.                     numeric = (**info).itemInfo[popupTypeinItem-1].numeric;
  1247.                     if (TrackPopup(popupCtl, where, str, numeric)) {
  1248.                         *itemHit = itemNumber;
  1249.                         return true;
  1250.                     } else {
  1251.                         theEvent->what = nullEvent;
  1252.                     }
  1253.                 } else if (readOnly && vScroll != nil) {
  1254.                     if ((part = FindControl(where, dlg, &control)) != 0 && control == vScroll) {
  1255.                         if (part == inThumb) {
  1256.                             TrackControl(vScroll, where, nil);
  1257.                             viewTop = (**hTE).viewRect.top;
  1258.                             destTop = (**hTE).destRect.top;
  1259.                             oldScroll = viewTop - destTop;
  1260.                             scrollValue = GetCtlValue(vScroll);
  1261.                             height = (**hTE).lineHeight;
  1262.                             newScroll = scrollValue * height;
  1263.                             scrollDiff = oldScroll - newScroll;
  1264.                             if (scrollDiff != 0) TEScroll(0, scrollDiff, hTE);
  1265.                         } else {
  1266.                             TrackControl(vScroll, where, (ProcPtr)ScrollAction);
  1267.                         }
  1268.                     }
  1269.                 }
  1270.             }
  1271.         }
  1272.     }
  1273.     if (isCommand) {
  1274.         if (HiWord(menuSelection) == kEditMenu) {
  1275.             theCommand = LoWord(menuSelection);
  1276.             switch (theCommand) {
  1277.                 case kCutItem:
  1278.                 case kCopyItem:
  1279.                     if (theCommand == kCopyItem) {
  1280.                         customCopyCommandHandler = (**info).customCopyCommandHandler;
  1281.                         if (customCopyCommandHandler != nil) {
  1282.                             (*customCopyCommandHandler)(dlg);
  1283.                             break;
  1284.                         }
  1285.                     }
  1286.                     if (password == nil) {
  1287.                         if (theCommand == kCutItem) {
  1288.                             TECut(hTE);
  1289.                         } else {
  1290.                             TECopy(hTE);
  1291.                         }
  1292.                         ZeroScrap();
  1293.                         TEToScrap();
  1294.                     } else {
  1295.                         ZeroScrap();
  1296.                         PutScrap(selEnd - selStart, 'TEXT', password + selStart);
  1297.                         TEFromScrap();
  1298.                         if (theCommand == kCutItem) {
  1299.                             TEDelete(hTE);
  1300.                             BlockMove(password + selEnd, password + selStart, pwLen - selEnd + 1);
  1301.                         }
  1302.                     }
  1303.                     setItemHit = theCommand == kCutItem;
  1304.                     break;
  1305.                 case kPasteItem:
  1306.                     TEFromScrap();
  1307.                     if (password == nil) {
  1308.                         TEPaste(hTE);
  1309.                     } else {
  1310.                         BlockMove(password + selEnd,
  1311.                             password + selStart + TEScrpLength,
  1312.                             pwLen - selEnd + 1);
  1313.                         BlockMove(*TEScrpHandle, 
  1314.                             password + selStart,
  1315.                             TEScrpLength);
  1316.                         nBullets = TEScrpLength;
  1317.                         TEDelete(hTE);
  1318.                         while (nBullets--) TEInsert("•", 1, hTE);
  1319.                     }
  1320.                     setItemHit = true;
  1321.                     break;
  1322.                 case kClearItem:
  1323.                     TEDelete(hTE);
  1324.                     setItemHit = true;
  1325.                     break;
  1326.                 case kSelectAllItem:
  1327.                     TESetSelect(0, 0x7fff, hTE);
  1328.                     break;
  1329.             }
  1330.         }
  1331.         HiliteMenu(0);
  1332.         if (setItemHit) {
  1333.             *itemHit = editField;
  1334.             return true;
  1335.         }
  1336.     }
  1337.     return false;
  1338. }
  1339.  
  1340.  
  1341.  
  1342. /*----------------------------------------------------------------------------
  1343.     MyModalDialog 
  1344.  
  1345.     Presents a modal dialog.
  1346.     
  1347.     Entry:    filterProc = pointer to filter proc.
  1348.             hasCancelButton = true if dialog has a cancel button.
  1349.             returnIsOK = true if Return key is equivalent to ok button.
  1350.             
  1351.     Exit:    itemHit = item number hit.
  1352. ----------------------------------------------------------------------------*/
  1353.  
  1354. void MyModalDialog (ModalFilterProcPtr filterProc, short *itemHit,
  1355.     Boolean hasCancelButton, Boolean returnIsOK)
  1356. {
  1357.     TDialogInfo **info;
  1358.  
  1359.     info = (TDialogInfo**)GetWRefCon(FrontWindow());
  1360.     (**info).returnIsOK = returnIsOK;
  1361.     (**info).hasCancelButton = hasCancelButton;
  1362.     TEFromScrap();
  1363.     ModalDialog(filterProc, itemHit);
  1364.     ZeroScrap();
  1365.     TEToScrap();
  1366. }
  1367.  
  1368.  
  1369.  
  1370. /*----------------------------------------------------------------------------
  1371.     ErrorMessage 
  1372.     
  1373.     Issues an error message alert.
  1374.     
  1375.     Entry:    msg = error message.
  1376. ----------------------------------------------------------------------------*/
  1377.  
  1378. void ErrorMessage (char *msg)
  1379. {
  1380.     DialogPtr dlg;
  1381.     short item;
  1382.  
  1383.     c2pstr(msg);
  1384.     ParamText((StringPtr)msg, "\p", "\p", "\p");
  1385.     p2cstr((StringPtr)msg);
  1386.     dlg = MyGetNewDialog(kErrDlg);
  1387.     SysBeep(1);
  1388.     MyModalDialog(DialogFilter, &item, false, true);
  1389.     MyDisposDialog(dlg);
  1390. }
  1391.  
  1392.  
  1393.  
  1394. /*----------------------------------------------------------------------------
  1395.     UnexpectedErrorMessage 
  1396.     
  1397.     Issues an unexpected error alert.
  1398.     
  1399.     Entry:    err = error number.
  1400. ----------------------------------------------------------------------------*/
  1401.  
  1402. void UnexpectedErrorMessage (OSErr err)
  1403. {
  1404.     Str255 errNumStr;
  1405.     DialogPtr dlg;
  1406.     short item;
  1407.  
  1408.     if (err == -1 || err == noErr) return;
  1409.     if (err == connectionClosing || err == connectionDoesntExist ||
  1410.         err == connectionTerminated) 
  1411.     {
  1412.         ErrorMessage("Lost connection to server.");
  1413.         return;
  1414.     }
  1415.     NumToString(err, errNumStr);
  1416.     ParamText(errNumStr, "\p", "\p", "\p");
  1417.     dlg = MyGetNewDialog(kUnexpectedErrDlg);
  1418.     SysBeep(1);
  1419.     MyModalDialog(DialogFilter, &item, false, true);
  1420.     MyDisposDialog(dlg);
  1421. }
  1422.  
  1423.  
  1424.  
  1425. /*----------------------------------------------------------------------------
  1426.     DrawNewsServerErrorMessageBozoText
  1427.     
  1428.     A user item procedure to draw the server error message bozo text.
  1429.     
  1430.     Entry:    dlg = pointer to dialog.
  1431.             item = item number.
  1432. ----------------------------------------------------------------------------*/
  1433.  
  1434. static pascal void DrawNewsServerErrorMessageBozoText (DialogPtr dlg, short item)
  1435. {
  1436.     short itemType;
  1437.     Rect box;
  1438.     Handle itemHandle;
  1439.     Handle text;
  1440.     short saveFont, saveSize;
  1441.     GrafPtr curPort;
  1442.  
  1443.     GetDItem(dlg, item, &itemType, &itemHandle, &box);
  1444.     text = GetResource('TEXT', kNewsServerErrorMessageBozoText);
  1445.     GetPort(&curPort);
  1446.     saveFont = curPort->txFont;
  1447.     saveSize = curPort->txSize;
  1448.     TextFont(applFont);
  1449.     TextSize(9);
  1450.     HLock(text);
  1451.     TextBox(*text, GetHandleSize(text), &box, teFlushDefault);
  1452.     HUnlock(text);
  1453.     TextFont(saveFont);
  1454.     TextSize(saveSize);
  1455. }
  1456.  
  1457.  
  1458.  
  1459. /*----------------------------------------------------------------------------
  1460.     NewsServerErrorMessageCopyHandler
  1461.     
  1462.     Handles the Edit menu Copy command for the news server error message dialog.
  1463.         
  1464.     Entry:    dlg = pointer to dialog.
  1465. ----------------------------------------------------------------------------*/
  1466.  
  1467. static void NewsServerErrorMessageCopyHandler (DialogPtr dlg)
  1468. {
  1469.     char str[516];
  1470.     Handle txtHandle, rsrcHandle;
  1471.  
  1472.     sprintf(str, "%#s\r\r%#s\r\r", gServerErrorMessageStaticText, 
  1473.         gServerErrorMessageTheMessage);
  1474.     PtrToHand(str, &txtHandle, strlen(str));
  1475.     rsrcHandle = GetResource('TEXT', kNewsServerErrorMessageBozoText);
  1476.     HLock(rsrcHandle);
  1477.     HandAndHand(rsrcHandle, txtHandle);
  1478.     HUnlock(rsrcHandle);
  1479.     ZeroScrap();
  1480.     HLock(txtHandle);
  1481.     PutScrap(GetHandleSize(txtHandle), 'TEXT', *txtHandle);
  1482.     MyDisposHandle(txtHandle);
  1483.     TEFromScrap();
  1484. }
  1485.  
  1486.  
  1487.  
  1488. /*----------------------------------------------------------------------------
  1489.   NewsServerErrorMessage 
  1490.   
  1491.   Issues a news server error message.
  1492.   
  1493.   Entry:    serverCommand = name of the command NewsWatcher tried to send
  1494.                   to the news server.
  1495.               serverResponse = error message as returned by the news server, terminated
  1496.                   by CR or LF.
  1497. ----------------------------------------------------------------------------*/
  1498.  
  1499. void NewsServerErrorMessage (char *serverCommand, char *serverResponse)
  1500. {
  1501.     DialogPtr dlg;
  1502.     short i, item;
  1503.  
  1504.     dlg = MyGetNewDialog(kServerErrDlg);
  1505.     SysBeep(1);
  1506.     for (i = 0; i < 255 && serverResponse[i] != CR && serverResponse[i] != LF; i++);
  1507.     BlockMove(serverResponse, gServerErrorMessageTheMessage+1, i);
  1508.     *gServerErrorMessageTheMessage = i;
  1509.     if (serverCommand == nil) {
  1510.         strcpy((char*)gServerErrorMessageStaticText,
  1511.             "A news server error occurred when NewsWatcher tried to connect to the server.");
  1512.     } else {
  1513.         sprintf((char*)gServerErrorMessageStaticText,
  1514.             "A news server error occurred in response to a NewsWatcher %s command.",
  1515.             serverCommand);
  1516.     }
  1517.     c2pstr((char*)gServerErrorMessageStaticText);
  1518.     DlgSetPString(dlg, kNewsServerErrorMessageStaticTextItem, gServerErrorMessageStaticText); 
  1519.     DlgSetPString(dlg, kNewsServerErrorMessageTheMessageItem, gServerErrorMessageTheMessage); 
  1520.     DlgSetUserItem(dlg, kNewsServerErrorMessageGrayBorderUserItem, DlgGrayBorderItem);    
  1521.     DlgSetUserItem(dlg, kNewsServerErrorMessageBozoTextUserItem, DrawNewsServerErrorMessageBozoText);
  1522.     SetDialogCustomCopyHandler(dlg, NewsServerErrorMessageCopyHandler);
  1523.     MyModalDialog(DialogFilter, &item, false, true);
  1524.     MyDisposDialog(dlg);
  1525. }
  1526.  
  1527.  
  1528.  
  1529. /*----------------------------------------------------------------------------
  1530.   MailOrFTPServerErrorMessage 
  1531.   
  1532.   Issues a mail or FTP server error message.
  1533.   
  1534.   Entry:    serverResponse = error message as returned by the server, terminated
  1535.                   by CR or LF.
  1536. ----------------------------------------------------------------------------*/
  1537.  
  1538. void MailOrFTPServerErrorMessage (char *serverResponse)
  1539. {
  1540.     DialogPtr dlg;
  1541.     short i, item;
  1542.     Str255 msg;
  1543.  
  1544.     dlg = MyGetNewDialog(kMailFTPErrDlg);
  1545.     SysBeep(1);
  1546.     for (i = 0; i < 255 && serverResponse[i] != CR && serverResponse[i] != LF; i++);
  1547.     BlockMove(serverResponse, msg+1, i);
  1548.     *msg = i;
  1549.     DlgSetPString(dlg, kMailFTPErrorMessageTheMessageItem, msg); 
  1550.     DlgSetUserItem(dlg, kMailFTPErrorMessageGrayBorderUserItem, DlgGrayBorderItem);    
  1551.     MyModalDialog(DialogFilter, &item, false, true);
  1552.     MyDisposDialog(dlg);
  1553. }
  1554.